/**************************************************************************//**
 * @item     CosyOS-II Config
 * @file     mcucfg_cmx.c
 * @brief    CMSIS Cortex-M Core Config File
 * @author   迟凯峰
 * @version  V2.1.0
 * @date     2024.03.31
 ******************************************************************************/

#include "..\System\os_var.h"
#ifdef __MCUCFG_CMX_H

s_u32_t  m_basepri = 1;
#if SYSCFG_TASKMSG == __ENABLED__
s_u32_t *m_taskmsg_psp;
#endif



/*
 * 中断挂起服务
 */

#if MCUCFG_PENDSVFIFO_DEPTH > 0
#if SYSCFG_PENDSVFIFO_MONITOR == __ENABLED__
s_u8_t mPendSV_FIFO_DepthMAX = 0;
#endif
void *mPendSV_FIFO[2][MCUCFG_PENDSVFIFO_DEPTH + 1]; /*!< 中断挂起服务缓存队列：FIFO0、FIFO1 */
#if MCUCFG_SYSSCHEME == 0
register void **mPendSV_P0 __ASM("r10");            /*!< FIFO0指针-全局寄存器变量 */
register void **mPendSV_P1 __ASM("r11");            /*!< FIFO1指针-全局寄存器变量 */
#else
void **mPendSV_P0;                                  /*!< FIFO0指针-全局内存变量 */
void **mPendSV_P1;                                  /*!< FIFO1指针-全局内存变量 */
#endif
volatile s_bool_t m_sign_fifo = true;               /*!< FIFO 互斥访问锁 */

/* 中断挂起服务装载器 */
#if MCUCFG_SYSSCHEME == 0
/* 方案一、全局寄存器变量 */
__ASM void mPendSV_Loader(void *sv)
{
	extern m_sign_fifo;
	
	ldr r1, =m_sign_fifo
	ldrb r2, [r1]
	cbz r2, __FIFO1
	
__FIFO0
	str r0, [r10,#4]!
	bx lr
	
__FIFO1
	str r0, [r11,#4]!
	bx lr
	
	nop
}

#elif MCUCFG_SYSSCHEME == 1
/* 方案二、互斥访问指令 */
__ASM void mPendSV_Loader(void *sv)
{
	extern m_sign_fifo;
	extern mPendSV_P0;
	extern mPendSV_P1;
	
	ldr r1, =m_sign_fifo
	ldrb r2, [r1]
	cbz r2, __FIFO1
	
__FIFO0
	ldr r1, =mPendSV_P0
	b __LOAD
	
__FIFO1
	ldr r1, =mPendSV_P1
	
__LOAD
	ldrex r2, [r1]
	add r2, #4
	strex r3, r2, [r1]
	cmp r3, #0
	bne __LOAD
	
	str r0, [r2]
	bx lr
}

#elif MCUCFG_SYSSCHEME == 2
/* 方案三、关中断 */
__ASM void mPendSV_Loader(void *sv)
{
	extern m_sign_fifo;
	extern mPendSV_P0;
	extern mPendSV_P1;
	
	ldr r1, =m_sign_fifo
	ldrb r2, [r1]
	cbz r2, __FIFO1
	
__FIFO0
	ldr r1, =mPendSV_P0
	b __LOAD
	
__FIFO1
	ldr r1, =mPendSV_P1
	
__LOAD
	mrs r3, primask /*!< 保存原primask */
	cpsid i         /*!< 关闭总中断 */
	ldr r2, [r1]
	add r2, #4
	str r2, [r1]
	msr primask, r3 /*!< 恢复原primask */
	
	str r0, [r2]
	bx lr
	nop
}

#endif

/* 中断挂起服务处理器 */
void mPendSV_Handler(void)
{
	register void **p;
	register void *sv;
	#if SYSCFG_PENDSVFIFO_MONITOR == __ENABLED__
	register s_u8_t depth;
	#endif
	
__LABLE:
	m_sign_fifo = false;
	/* 独占访问FIFO0 */
	{
		#if SYSCFG_PENDSVFIFO_MONITOR == __ENABLED__
		depth = (s_u8_t)(mPendSV_P0 - mPendSV_FIFO[0]);
		if(depth > mPendSV_FIFO_DepthMAX){
			mPendSV_FIFO_DepthMAX = depth;
		}
		#endif
		p = mPendSV_FIFO[0];
		do{
			sv = *++p;
			(*sPendSV_Handler[*(const s_u8_t *)sv])(sv);
		}while(mPendSV_P0 > p);
		mPendSV_P0 = mPendSV_FIFO[0];
	}
	m_sign_fifo = true;
	if(mPendSV_P1 == mPendSV_FIFO[1]) return;
	/* 独占访问FIFO1 */
	{
		#if SYSCFG_PENDSVFIFO_MONITOR == __ENABLED__
		depth = (s_u8_t)(mPendSV_P1 - mPendSV_FIFO[1]);
		if(depth > mPendSV_FIFO_DepthMAX){
			mPendSV_FIFO_DepthMAX = depth;
		}
		#endif
		p = mPendSV_FIFO[1];
		do{
			sv = *++p;
			(*sPendSV_Handler[*(const s_u8_t *)sv])(sv);
		}while(mPendSV_P1 > p);
		mPendSV_P1 = mPendSV_FIFO[1];
	}
	if(mPendSV_P0 > mPendSV_FIFO[0]) goto __LABLE;
}

#endif



/*
 * 任务切换
 */

__ASM void mTaskStack_PUSHPOP(s_bool_t f, void *p)
{
	extern s_task_current;
	extern s_sign_taskmgr;
	extern s_pc;
	
	PRESERVE8
	isb
	ldr r2, =s_task_current
	cbz r0, __POP
	mrs r0, psp
	
__TASKPC
	IF SYSCFG_TASKPC_MONITOR == __ENABLED__
	ldr r3, =s_sign_taskmgr
	ldrb r3, [r3]
	cbz r3, __PUSH
	mov r3, r0
	add r3, #24
	ldmia r3, {r2}
	ldr r3, =s_pc
	str r2, [r3]
	ldr r2, =s_task_current
	ENDIF
	
__PUSH
	IF MCUCFG_HARDWAREFPU == __ENABLED__
	vstmdb r0!, {s16-s31}
	ENDIF
	stmdb r0!, {MCUCFG_CALLEE_REG}
	ldr r3, [r2]
	str r0, [r3]
	
__POP
	str r1, [r2]
	ldr r0, [r1]
	ldmia r0!, {MCUCFG_CALLEE_REG}
	IF MCUCFG_HARDWAREFPU == __ENABLED__
	vldmia r0!, {s16-s31}
	ENDIF
	msr psp, r0
	bx lr
	nop
}



#endif
